package com.icongyou.enterprise.talent_marking.controller;

import com.icongyou.enterprise.common.result.Result;
import com.icongyou.enterprise.talent_marking.entity.dto.MarkRequest;
import com.icongyou.enterprise.talent_marking.entity.vo.StudentBasicInfo;
import com.icongyou.enterprise.talent_marking.entity.vo.StudentFocusMark;
import com.icongyou.enterprise.talent_marking.service.StudentFocusMarkService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
@DisplayName("学生关注标记控制器测试")
class StudentFocusMarkControllerTest {

    @Mock
    private StudentFocusMarkService studentFocusMarkService;

    @InjectMocks
    private StudentFocusMarkController controller;

    private String userId;
    private String studentId;
    private MarkRequest markRequest;

    @BeforeEach
    void setUp() {
        userId = "USER001";
        studentId = "STUDENT001";

        markRequest = new MarkRequest();
        markRequest.setUserId(userId);
        markRequest.setStudentId(studentId);
        markRequest.setTag(1);
    }

    // ==================== markStudent 测试 ====================

    @Test
    @DisplayName("标记学生 - 成功创建")
    void testMarkStudent_SuccessCreate() {
        // Arrange
        StudentFocusMark mark = new StudentFocusMark();
        mark.setId("MARK001");
        Result serviceResult = Result.success("标记已创建", mark);
        when(studentFocusMarkService.markStudent(any(MarkRequest.class))).thenReturn(serviceResult);

        // Act
        Result result = controller.markStudent(markRequest);

        // Assert
        assertEquals(200, result.getCode());
        assertEquals("标记已创建", result.getMessage());
        assertNotNull(result.getData());
        verify(studentFocusMarkService).markStudent(markRequest);
    }

    @Test
    @DisplayName("标记学生 - 成功更新")
    void testMarkStudent_SuccessUpdate() {
        // Arrange
        StudentFocusMark mark = new StudentFocusMark();
        mark.setId("MARK001");
        Result serviceResult = Result.success("标记已更新", mark);
        when(studentFocusMarkService.markStudent(any(MarkRequest.class))).thenReturn(serviceResult);

        // Act
        Result result = controller.markStudent(markRequest);

        // Assert
        assertEquals(200, result.getCode());
        assertEquals("标记已更新", result.getMessage());
        verify(studentFocusMarkService).markStudent(markRequest);
    }

    @Test
    @DisplayName("标记学生 - 重点关注标签")
    void testMarkStudent_ImportantTag() {
        // Arrange
        markRequest.setTag(1);
        Result serviceResult = Result.success("标记已创建", new StudentFocusMark());
        when(studentFocusMarkService.markStudent(any(MarkRequest.class))).thenReturn(serviceResult);

        // Act
        Result result = controller.markStudent(markRequest);

        // Assert
        assertEquals(200, result.getCode());
        verify(studentFocusMarkService).markStudent(markRequest);
    }

    @Test
    @DisplayName("标记学生 - 一般关注标签")
    void testMarkStudent_NormalTag() {
        // Arrange
        markRequest.setTag(0);
        Result serviceResult = Result.success("标记已创建", new StudentFocusMark());
        when(studentFocusMarkService.markStudent(any(MarkRequest.class))).thenReturn(serviceResult);

        // Act
        Result result = controller.markStudent(markRequest);

        // Assert
        assertEquals(200, result.getCode());
        verify(studentFocusMarkService).markStudent(markRequest);
    }

    // ==================== unmarkStudent 测试 ====================

    @Test
    @DisplayName("取消关注 - 成功")
    void testUnmarkStudent_Success() {
        // Arrange
        Result serviceResult = Result.success();
        when(studentFocusMarkService.unmarkStudent(userId, studentId)).thenReturn(serviceResult);

        // Act
        Result result = controller.unmarkStudent(userId, studentId);

        // Assert
        assertEquals(200, result.getCode());
        verify(studentFocusMarkService).unmarkStudent(userId, studentId);
    }

    @Test
    @DisplayName("取消关注 - 使用不同参数")
    void testUnmarkStudent_DifferentParameters() {
        // Arrange
        String differentUserId = "USER002";
        String differentStudentId = "STUDENT002";
        Result serviceResult = Result.success();
        when(studentFocusMarkService.unmarkStudent(differentUserId, differentStudentId))
                .thenReturn(serviceResult);

        // Act
        Result result = controller.unmarkStudent(differentUserId, differentStudentId);

        // Assert
        assertEquals(200, result.getCode());
        verify(studentFocusMarkService).unmarkStudent(differentUserId, differentStudentId);
    }

    // ==================== getFocusStudentsByUser 测试 ====================

    @Test
    @DisplayName("获取用户关注列表 - 有数据")
    void testGetFocusStudentsByUser_WithData() {
        // Arrange
        StudentFocusMark mark1 = new StudentFocusMark();
        mark1.setId("MARK001");
        mark1.setStudentId("STUDENT001");
        mark1.setTag(1);

        StudentFocusMark mark2 = new StudentFocusMark();
        mark2.setId("MARK002");
        mark2.setStudentId("STUDENT002");
        mark2.setTag(0);

        List<StudentFocusMark> marks = Arrays.asList(mark1, mark2);
        Result serviceResult = Result.success(marks);
        when(studentFocusMarkService.getFocusStudentsByUser(userId)).thenReturn(serviceResult);

        // Act
        Result result = controller.getFocusStudentsByUser(userId);

        // Assert
        assertEquals(200, result.getCode());
        assertNotNull(result.getData());
        @SuppressWarnings("unchecked")
        List<StudentFocusMark> resultList = (List<StudentFocusMark>) result.getData();
        assertEquals(2, resultList.size());
        verify(studentFocusMarkService).getFocusStudentsByUser(userId);
    }

    @Test
    @DisplayName("获取用户关注列表 - 空列表")
    void testGetFocusStudentsByUser_EmptyList() {
        // Arrange
        Result serviceResult = Result.success(Collections.emptyList());
        when(studentFocusMarkService.getFocusStudentsByUser(userId)).thenReturn(serviceResult);

        // Act
        Result result = controller.getFocusStudentsByUser(userId);

        // Assert
        assertEquals(200, result.getCode());
        verify(studentFocusMarkService).getFocusStudentsByUser(userId);
    }

    // ==================== isStudentFocusMarked 测试 ====================

    @Test
    @DisplayName("检查是否已关注 - 已关注")
    void testIsStudentFocusMarked_AlreadyMarked() {
        // Arrange
        Result serviceResult = Result.success(true);
        when(studentFocusMarkService.isStudentFocusMarked(userId, studentId)).thenReturn(serviceResult);

        // Act
        Result result = controller.isStudentFocusMarked(userId, studentId);

        // Assert
        assertEquals(200, result.getCode());
        assertTrue((Boolean) result.getData());
        verify(studentFocusMarkService).isStudentFocusMarked(userId, studentId);
    }

    @Test
    @DisplayName("检查是否已关注 - 未关注")
    void testIsStudentFocusMarked_NotMarked() {
        // Arrange
        Result serviceResult = Result.success(false);
        when(studentFocusMarkService.isStudentFocusMarked(userId, studentId)).thenReturn(serviceResult);

        // Act
        Result result = controller.isStudentFocusMarked(userId, studentId);

        // Assert
        assertEquals(200, result.getCode());
        assertFalse((Boolean) result.getData());
        verify(studentFocusMarkService).isStudentFocusMarked(userId, studentId);
    }

    // ==================== getFocusStudentInfo 测试 ====================

    @Test
    @DisplayName("获取关注学生详细信息 - 有数据")
    void testGetFocusStudentInfo_WithData() {
        // Arrange
        StudentBasicInfo info1 = new StudentBasicInfo();
        info1.setStudentId("STUDENT001");
        info1.setRealName("张三");
        info1.setTag(1);

        StudentBasicInfo info2 = new StudentBasicInfo();
        info2.setStudentId("STUDENT002");
        info2.setRealName("李四");
        info2.setTag(0);

        List<StudentBasicInfo> infos = Arrays.asList(info1, info2);
        Result<List<StudentBasicInfo>> serviceResult = Result.success("获取关注学生成功", infos);
        when(studentFocusMarkService.getFocusStudentInfo(userId)).thenReturn(serviceResult);

        // Act
        Result<List<StudentBasicInfo>> result = controller.getFocusStudentInfo(userId);

        // Assert
        assertEquals(200, result.getCode());
        assertEquals("获取关注学生成功", result.getMessage());
        assertNotNull(result.getData());
        assertEquals(2, result.getData().size());
        verify(studentFocusMarkService).getFocusStudentInfo(userId);
    }

    @Test
    @DisplayName("获取关注学生详细信息 - 空列表")
    void testGetFocusStudentInfo_EmptyList() {
        // Arrange
        Result<List<StudentBasicInfo>> serviceResult = 
                Result.success("暂无关注学生", Collections.emptyList());
        when(studentFocusMarkService.getFocusStudentInfo(userId)).thenReturn(serviceResult);

        // Act
        Result<List<StudentBasicInfo>> result = controller.getFocusStudentInfo(userId);

        // Assert
        assertEquals(200, result.getCode());
        assertEquals("暂无关注学生", result.getMessage());
        verify(studentFocusMarkService).getFocusStudentInfo(userId);
    }

    // ==================== 参数传递测试 ====================

    @Test
    @DisplayName("标记学生 - 完整的MarkRequest对象")
    void testMarkStudent_CompleteMarkRequest() {
        // Arrange
        MarkRequest completeRequest = new MarkRequest();
        completeRequest.setUserId("USER001");
        completeRequest.setStudentId("STUDENT001");
        completeRequest.setTag(1);

        Result serviceResult = Result.success();
        when(studentFocusMarkService.markStudent(any(MarkRequest.class))).thenReturn(serviceResult);

        // Act
        Result result = controller.markStudent(completeRequest);

        // Assert
        assertEquals(200, result.getCode());
        verify(studentFocusMarkService).markStudent(completeRequest);
    }

    @Test
    @DisplayName("获取关注列表 - PathVariable传递")
    void testGetFocusStudentsByUser_PathVariable() {
        // Arrange
        String pathUserId = "USER_FROM_PATH";
        Result serviceResult = Result.success(Collections.emptyList());
        when(studentFocusMarkService.getFocusStudentsByUser(pathUserId)).thenReturn(serviceResult);

        // Act
        Result result = controller.getFocusStudentsByUser(pathUserId);

        // Assert
        assertEquals(200, result.getCode());
        verify(studentFocusMarkService).getFocusStudentsByUser(pathUserId);
    }

    @Test
    @DisplayName("检查关注状态 - RequestParam传递")
    void testIsStudentFocusMarked_RequestParams() {
        // Arrange
        String queryUserId = "USER_FROM_QUERY";
        String queryStudentId = "STUDENT_FROM_QUERY";
        Result serviceResult = Result.success(true);
        when(studentFocusMarkService.isStudentFocusMarked(queryUserId, queryStudentId))
                .thenReturn(serviceResult);

        // Act
        Result result = controller.isStudentFocusMarked(queryUserId, queryStudentId);

        // Assert
        assertEquals(200, result.getCode());
        verify(studentFocusMarkService).isStudentFocusMarked(queryUserId, queryStudentId);
    }

    // ==================== 业务流程测试 ====================

    @Test
    @DisplayName("完整流程 - 标记后再查询")
    void testFullFlow_MarkThenQuery() {
        // Arrange
        StudentFocusMark createdMark = new StudentFocusMark();
        createdMark.setId("MARK001");
        createdMark.setStudentId(studentId);
        createdMark.setTag(1);

        Result markResult = Result.success("标记已创建", createdMark);
        Result queryResult = Result.success(true);

        when(studentFocusMarkService.markStudent(any(MarkRequest.class))).thenReturn(markResult);
        when(studentFocusMarkService.isStudentFocusMarked(userId, studentId)).thenReturn(queryResult);

        // Act
        Result markResponse = controller.markStudent(markRequest);
        Result queryResponse = controller.isStudentFocusMarked(userId, studentId);

        // Assert
        assertEquals(200, markResponse.getCode());
        assertEquals(200, queryResponse.getCode());
        assertTrue((Boolean) queryResponse.getData());

        verify(studentFocusMarkService).markStudent(markRequest);
        verify(studentFocusMarkService).isStudentFocusMarked(userId, studentId);
    }

    @Test
    @DisplayName("完整流程 - 标记后再取消")
    void testFullFlow_MarkThenUnmark() {
        // Arrange
        Result markResult = Result.success("标记已创建", new StudentFocusMark());
        Result unmarkResult = Result.success();

        when(studentFocusMarkService.markStudent(any(MarkRequest.class))).thenReturn(markResult);
        when(studentFocusMarkService.unmarkStudent(userId, studentId)).thenReturn(unmarkResult);

        // Act
        Result markResponse = controller.markStudent(markRequest);
        Result unmarkResponse = controller.unmarkStudent(userId, studentId);

        // Assert
        assertEquals(200, markResponse.getCode());
        assertEquals(200, unmarkResponse.getCode());

        verify(studentFocusMarkService).markStudent(markRequest);
        verify(studentFocusMarkService).unmarkStudent(userId, studentId);
    }
}
